package gcontent.channel.dns;

import gcontent.channel.Channel;
import gcontent.channel.error.ChannelEx;
import gcontent.entities.Content;
import gcontent.entities.Site;
import gcontent.entities.content.ContentManager;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import java.util.ArrayList;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;

public class ChannelDNS extends Channel {

	public static final String TYPE_DNS = "DNS";
	
	/*
		** NS -> Name server record maps a domain name to a list of DNS servers authoritative for that domain. 
		A -> Address record maps a hostname to a 32-bit IPv4 address
		SOA -> Start of authority record specifies the DNS server providing authoritative information about an Internet domain.
		MX -> Mail exchange record maps a domain name to a list of mail exchange servers for that domain.
		AAAA -> AAA record IPv6 address record maps a hostname to a 128-bit IPv6 address.
		CNAME -> Canonical name record is an alias of one name to another.
		PTR -> Pointer record maps an IPv4 address to the canonical name for that host.Setting up a PTR record for a hostname in the in-addr.arpa domain that corresponds to an IP address implements reverse DNS lookup for that address.
		SRV -> It is a generalized service location record.
		TXT -> This record is used to implement the Sender Policy Framework.
	*/
	private static final String [] records = {"NS", "A", "SOA", "MX", "AAAA", "CNAME", "PTR", "SRV", "TXT"};
	
	private String host = "";
	private Site site = null;
	private ArrayList<String>[] values;
	
	public void setHost(String host)
	{
		this.host = host;
	}
	
	public ArrayList<String> getServerRecords(String server, String [] record_name) throws NamingException 
	{
		ArrayList<String> ret = new ArrayList<String>();
		
		InitialDirContext iDirC = null;
        Attributes attributes = null;
        NamingEnumeration attributes_enum = null;
        
        
        iDirC = new InitialDirContext();
        attributes = iDirC.getAttributes(server, record_name);
        
        attributes_enum = attributes.getAll();
        
        while (attributes_enum.hasMore()) {
        	Attribute attr = (Attribute)attributes_enum.next();
        	NamingEnumeration e = null;
        	attr.getAll();
        	
    		for (e = attr.getAll(); e.hasMore();)
    		{
    			String value = e.next().toString();
    			ret.add(value);
    		}
    		if (e != null)
    			e.close();           	
        }           	

        attributes_enum.close();
		
		return ret;
	}
	
	public void connect(Site site) throws ChannelEx 
	{
		String normal_host = null;
		
		try {
			normal_host = gcontent.utils.URLUtils.splitWorldWideWeb(gcontent.utils.IP.NormalizeAddress(gcontent.utils.URLUtils.splitProtocol("site.getPath()")).getHostName());
		} catch (Exception ex) {
			ex.printStackTrace();
			return;
		}
		
		setHost("dns:/" + normal_host);
		this.site = site;
		
		if (host == null ||  this.host.length() <= 0)
			throw new ChannelEx("Host can't be null");
		
		
		values = new ArrayList[records.length];		
		for (int i = 0; i < records.length; i++) {
			try {
				values[i] = getServerRecords(host, new String[] {records[i]});	
			} catch (Exception ex) {
				throw new ChannelEx(ex);
			}			
		}
	}

	public void disconnect() throws ChannelEx 
	{
	}

	public Content getContent(Site site) throws ChannelEx 
	{
		Content content;
		String body = "";
		
		try {
			content = ContentManager.getContent(TYPE_DNS);
		} catch (Exception ex) {
			throw new ChannelEx(ex);
		}
	
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				if (values[i].size() > 0) {
					body += records[i] + ":";
					for (int j = 0; j < values[i].size(); j++) {
						body += gcontent.utils.URLUtils.normalizeDNSIp(values[i].get(j));
						if (j < values[i].size() - 1 )
							body += ";"; 
					}
					body += "\n";
				}				
			}
		}
		
		content.setBody(body.getBytes());
		content.setParentSite(this.site);
		
		return content;
	}
	
	public String getStringContent() throws ChannelEx 
	{
		String body = "";
		
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				if (values[i].size() > 0) {
					body += records[i] + ":";
					for (int j = 0; j < values[i].size(); j++) {
						body += gcontent.utils.URLUtils.normalizeDNSIp(values[i].get(j));
						if (j < values[i].size() - 1 )
							body += ";"; 
					}
					body += "\n";
				}				
			}
		}
		
		return body;
	}

	public String getProtocol() 
	{
		return TYPE_DNS;
	}

}
